package club.ruanx.search.controller;

import club.ruanx.bean.PageBean;
import club.ruanx.movie.common.constraint.MovieRedisConstraint;
import club.ruanx.movie.vo.MovieVO;
import club.ruanx.search.service.SolrMovieService;
import club.ruanx.solr.entity.SolrMovie;
import club.ruanx.solr.param.SolrMovieParam;
import club.ruanx.util.BeanUtils;
import club.ruanx.util.CollectionUtils;
import club.ruanx.util.PagingUtils;
import com.alibaba.fastjson.JSON;
import org.apache.solr.client.solrj.SolrServerException;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 阮胜
 * @date 2018/11/23 17:00
 */
@RestController
@RequestMapping("/movie")
public class SolrMovieController {
    private final SolrMovieService solrMovieService;
    private final RedisTemplate<String, Object> redisTemplate;

    public SolrMovieController(SolrMovieService solrMovieService, RedisTemplate<String, Object> redisTemplate) {
        this.solrMovieService = solrMovieService;
        this.redisTemplate = redisTemplate;
    }


    @GetMapping("/find")
    public List<SolrMovie> query(String name, PageBean pageBean) {
        return solrMovieService.findByNameLike(name, pageBean).getContent();
    }

    @PostMapping("/save")
    public boolean save(@RequestBody SolrMovieParam solrMovieParam) {
        solrMovieService.save(solrMovieParam);
        return true;
    }

    @GetMapping("/search")
    public List<MovieVO> search(@NotEmpty String k, PageBean pageBean) {
        pageBean.setSize(12);
        //增加关键词热度
        redisTemplate.opsForZSet().incrementScore(MovieRedisConstraint.MOVIE_SEARCH_KEY_TIMES_ZSET, k, 1);
        //获取模糊级别
        int distance = getQueryDistance(k);
        //根据模糊级别搜索
        Page<SolrMovie> solrMoviePage = solrMovieService.searchMovieWithDistance(k, distance, pageBean);
        List<SolrMovie> solrMovieList = solrMoviePage.getContent();
        //如果模糊搜索到的结果为空，则使用非模糊级别搜索
        if (CollectionUtils.isEmpty(solrMovieList)) {
            if (k.length() <= 4) {
                solrMovieList = solrMovieService.searchMovieWithNullDistance(k, pageBean).getContent();
            } else {
                String newKey = k.substring(0, k.length() - 1);
                solrMovieList = solrMovieService.searchMovieWithNullDistance(newKey, pageBean).getContent();
            }
            if (solrMovieList.size() == 0) {
                String newKey = k.substring(0, k.length() - distance);
                solrMovieList = solrMovieService.searchMovieWithNullDistance(newKey, pageBean).getContent();
            }
            if (solrMovieList.size() == 0) {
                solrMovieList = solrMovieService.searchMovie(k, pageBean).getContent().stream()
                        .filter(solrMovie -> solrMovie.getScore() >= 6)
                        .collect(Collectors.toList());
            }
        }
        PagingUtils.setNgxAdminPagingHeader(solrMovieList.size());
        //数据适配
        return solrMovieList.stream()
                .map(solrMovie -> {
                    MovieVO movieVO = new MovieVO();
                    BeanUtils.copyPropertiesIgnoreNull(solrMovie, movieVO);
                    String[] types = JSON.parseArray(solrMovie.getTypes(), String.class).toArray(new String[0]);
                    String[] languages = JSON.parseArray(solrMovie.getLanguages(), String.class).toArray(new String[0]);
                    String[] areas = JSON.parseArray(solrMovie.getAreas(), String.class).toArray(new String[0]);
                    movieVO.setTypes(types);
                    movieVO.setLanguages(languages);
                    movieVO.setAreas(areas);
                    return movieVO;
                }).collect(Collectors.toList());
    }

    private int getQueryDistance(String k) {
        if (k.length() == 1) {
            return 0;
        } else if (k.length() < 5) {
            return 1;
        } else {
            return 2;
        }
    }

    @GetMapping("/analysis")
    public Set<String> analyzeField(String field) throws IOException, SolrServerException {
        return solrMovieService.analyzeField(field);
    }

    @DeleteMapping("/delete/{movieId}")
    public boolean delete(@PathVariable String movieId) {
        return solrMovieService.delete(movieId);
    }
}
